package org.springside.modules.orm.hibernate;

import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.orm.Page;

/**
 * 默认的领域对象业务管理类基类,提供默认的泛型DAO成员变量.
 * 
 * @param <T>
 *            领域对象类型
 * @param <PK>
 *            领域对象的主键类型
 * 
 *            eg. public class UserManager extends DefaultEntityManager<User,
 *            Long>{ }
 * 
 * @author calvin
 */
@Transactional
public class DefaultEntityManager<T, PK extends Serializable> extends
		EntityManager<T, PK> {
	public static final String DAFAULT_STRING_NULL_VALUE = "-1";
	public static final Long DAFAULT_LONG_NULL_VALUE = -1l;
	public static final SimpleDateFormat dateTimeSdf = new SimpleDateFormat(
			"yyyyMMddhhmmss");
	public static final SimpleDateFormat dateSdf = new SimpleDateFormat(
			"yyyyMMdd");
	public static final int DEFAULT_RESULT_SIZE = 0;

	/**
	 * NamedQuery 查询方式
	 * 
	 * @param page
	 * @param namedQuery
	 * @param values
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Page<T> find(Page<T> page, String namedQuery, Object... values) {
		Query query = getEntityDao().getSession().getNamedQuery(namedQuery);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		getEntityDao().setPageParameter(query, page);
		page.setResult(query.list());
		return page;
	}

	@SuppressWarnings("unchecked")
	public List<T> find(List<T> list, String namedQuery, Object... values) {
		Query query = getEntityDao().getSession().getNamedQuery(namedQuery);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				query.setParameter(i, values[i]);
			}
		}
		query.list();
		return query.list();
	}

	@SuppressWarnings("unchecked")
	protected Object getParamValue(Map<String, Object> param, String key,
			Class clazz) {
		Object value = this.getParamValue(param, key);
		if (value == null || clazz == null) {
			return value;
		}
		if (clazz.equals(Integer.class)) {
			if (value instanceof String) {
				return Integer.valueOf((String) value);
			}
			if (value instanceof String[]) {
				return Integer.valueOf(((String[]) value)[0]);
			}
		} else if (clazz.equals(Long.class)) {
			if (value instanceof String) {
				return Long.valueOf((String) value);
			}
			if (value instanceof String[]) {
				return Long.valueOf(((String[]) value)[0]);
			}
		} else if (clazz.equals(Date.class)) {
			if (value instanceof String) {
				return convertStringToDate((String) value);
			}
			if (value instanceof String[]) {
				return convertStringToDate(((String[]) value)[0]);
			}
		} else if (clazz.equals(Boolean.class)) {
			if (value instanceof String) {
				return Boolean.valueOf((String) value);
			}
			if (value instanceof String[]) {
				return Boolean.valueOf(((String[]) value)[0]);
			}
		}
		return value;
	}

	protected Date convertStringToDate(String dateStr) {
		if (dateStr == null || dateStr.length() < 8) {
			return null;
		}
		dateStr = dateStr.replaceAll("-", "");
		dateStr = dateStr.replaceAll(":", "");
		dateStr = dateStr.replaceAll(" ", "");
		dateStr = dateStr.replaceAll("/", "");
		dateStr = dateStr.replaceAll(".", "");
		try {
			return dateStr.length() == 8 ? dateSdf.parse(dateStr) : dateStr
					.length() == 14 ? dateTimeSdf.parse(dateStr) : null;
		} catch (ParseException e) {
			return null;
		}
	}

	public Object getParamValue(Map<String, Object> param, String key) {
		if (param == null || key == null) {
			return null;
		}
		if (!isParamNotNull(param, key)) {
			return null;
		}
		Object value = param.get(key);
		if (value instanceof String[]) {
			String[] val = (String[]) value;
			if (val.length == 1) {
				return val[0];
			}
		}
		return value;
	}

	@SuppressWarnings("unchecked")
	public boolean isParamNotNull(Map<String, Object> param, String key) {
		if (param == null || key == null) {
			return false;
		}
		Object value = param.get(key);
		if (value == null) {
			return false;
		}
		if (value instanceof String) {
			if ("".equals(((String) value).trim())) {
				return false;
			}
		}

		if (value instanceof String[]) {
			String[] val = (String[]) value;
			if (val.length == 0 || val[0] == null || "".equals(val[0].trim())) {
				return false;
			}
		}

		if (value instanceof Collection
				|| value.getClass().getSuperclass().equals(Collection.class)) {
			Collection val = (Collection) value;
			if (val.size() == 0) {
				return false;
			}
		}
		return true;
	}
}
